#include "serialassist.h"



serialassist::serialassist(QWidget* parent)
    : QMainWindow(parent)
    , ui(new Ui_serialassist)
{
    // 初始化UI
    ui->setupUi(this);

    // 初始化串口对象
    serialPort = new QSerialPort();

    // 初始化定时器
    priecSendTimer = new QTimer();
    ui->spbPriecSendTimer->setMaximum(2147483647);
    ui->spbPriecSendTimer->setValue(1000);
    priecSendTimer->setInterval(1000);//默认周期1000ms

    // 初始化串口配置
    initPortConfig();

    // 串口接收函数关联
    connect(serialPort,SIGNAL(readyRead()),this,SLOT(readData())); // 接收
    connect(serialPort,&QSerialPort::errorOccurred, this, &serialassist::handleError);
    connect(priecSendTimer,&QTimer::timeout,this,[=](){on_btnSend_clicked();}); // 定时发送
    
}

serialassist::~serialassist()
{
    // 关闭串口
    if(serialPort->isOpen() == true)
        serialPort->close();
    delete ui; 
}

/**
 * @brief 扫描串口按键回调函数
 * 
 */
void serialassist::on_btnScanPort_clicked()
{
    // 扫描串口
    this->scanPorts();

    qDebug() << "btnScanPort call_back";
}

/**
 * @brief 打开串口按键回调函数
 * 
 */
void serialassist::on_btnOpenPort_clicked()
{
    if(ui->btnOpenPort->text() == QObject::tr("打开串口"))
    {
        serialPort->setPortName(ui->cmbPortName->currentText());
        serialPort->setBaudRate(ui->cmbBaudRate->currentText().toInt());
        serialPort->setStopBits(to_convert_stopbit(ui->cmbDataBits->currentText()));
        serialPort->setDataBits(to_convert_databit(ui->cmbStopBits->currentText()));
        serialPort->setParity(to_convert_paritybit(ui->cmbParity->currentText()));
        if(serialPort->open(QIODevice::ReadWrite))
        {
            ui->btnOpenPort->setText(QObject::tr("关闭串口"));
            // 禁用
            setControlsEnabled(false);
            ui->btnScanPort->setDisabled(true);

        }
        else 
        {
            QMessageBox::critical(this, "错误", "串口打开失败！");
        }
        
    }
    else if(ui->btnOpenPort->text() == QObject::tr("关闭串口"))
    {
        // 关闭串口
        if(serialPort->isOpen() == true)
            serialPort->close();
        ui->btnOpenPort->setText(QObject::tr("打开串口"));
        // 解禁
        setControlsEnabled(true);
        ui->btnScanPort->setEnabled(true);

    }

    qDebug() << "btnOpenPort call_back";
    qDebug() << serialPort->isOpen();
}

/**
 * @brief 串口发送按键
 * 
 */
void serialassist::on_btnSend_clicked()
{
    int send_cnt;

    // 检查串口是否打开
    if(!serialPort->isOpen()){
        QMessageBox::warning(this, "警告", "请先打开串口！");
        return;
    }
    QString sendData = ui->txtSend->toPlainText();
    if(sendData.isEmpty()) return;

    // HEX发送
    if(ui->chkHexSend->isChecked()){
        QByteArray hexData = QByteArray::fromHex(sendData.toLatin1());
        send_cnt = serialPort->write(hexData);
    }
    else{
        // if(ui->chkNewLine->isChecked()){
        //     sendData += "\r\n";
        // }
        send_cnt = serialPort->write(sendData.toLocal8Bit());
    }

    // 刷新计数
    sendByteCnt += send_cnt;
    ui->lcdSendByteCnt->display(sendByteCnt);

}

void serialassist::on_btnClearRev_clicked()
{
    ui->plainTxtRev->clear();
    qDebug() << "btnClearRev call_back";
}
void serialassist::on_btnClearSend_clicked()
{
    ui->txtSend->clear();
    qDebug() << "btnClearSend call_back";
}

void serialassist::on_btnResetCnt_clicked()
{
    // 计数清0
    sendByteCnt = 0;
    revByteCnt = 0;
    ui->lcdSendByteCnt->display(sendByteCnt);
    ui->lcdRevByteCnt->display(revByteCnt);
}


void serialassist::on_chkPriecSend_stateChanged(int arg1)
{
    // 未选中
    if(arg1 == false) 
    {
        priecSendTimer->stop(); // 关闭定时器
        ui->spbPriecSendTimer->setEnabled(true); // 使能周期输入文本框
    }
    else //选中，开始周期发送
    {
        // 检查串口是否打开
        if(!serialPort->isOpen()){
            ui->chkPriecSend->setCheckState(Qt::CheckState::Unchecked);
            QMessageBox::warning(this, "警告", "请先打开串口！");
            return;
        }
        
        priecSendTimer->start(ui->spbPriecSendTimer->text().toInt()); // 启动周期发送定时器
        ui->spbPriecSendTimer->setEnabled(false); // 失能周期输入文本框

    }
}

/**
 * @brief 串口接收数据
 * 
 */
void serialassist::readData()
{
    QByteArray data = serialPort->readAll();
    if(data.isEmpty()) return;
    
    
    if(ui->chkHexDisplay->isChecked()){
        QString hexString = data.toHex(' ').toUpper();
        ui->plainTxtRev->insertPlainText(hexString + " ");
    }
    else{
        QString text = QString::fromLocal8Bit(data);
        ui->plainTxtRev->insertPlainText(text);
    }
    
    // 自动滚动
    QTextCursor cursor = ui->plainTxtRev->textCursor();
    cursor.movePosition(QTextCursor::End);
    ui->plainTxtRev->setTextCursor(cursor);

    // 刷新计数
    revByteCnt += data.size();
    ui->lcdRevByteCnt->display(revByteCnt);
}

/**
 * @brief 串口异常处理
 * 
 */
void serialassist::handleError(QSerialPort::SerialPortError error)
{
    if(error == QSerialPort::ResourceError){
        QMessageBox::critical(this, "错误", "串口连接已断开！");
        if(serialPort->isOpen())
            serialPort->close();
        ui->btnOpenPort->setText("打开串口");
        // setControlsEnabled(true);
    }
    qDebug() << error;
    qDebug() << "handleError call_back";
}

/**
 * @brief 串口初始化配置
 * 
 */
void serialassist::initPortConfig()
{
    // 初始化时扫描一次串口
    scanPorts();

    // 波特率
    ui->cmbBaudRate->addItems({"1200", "2400", "4800", "9600", "19200", "38400", "57600", "115200"});
    ui->cmbBaudRate->setCurrentIndex(3); // 默认9600

    // 数据位
    ui->cmbDataBits->addItems({"5", "6", "7", "8"});
    ui->cmbDataBits->setCurrentIndex(3); // 默认8

    // 校验位
    ui->cmbParity->addItems({"None", "Even", "Odd", "Space", "Mark"});

    // 停止位
    ui->cmbStopBits->addItems({"1", "1.5", "2"});
}

/**
 * @brief 扫描串口端口号
 * 
 */
void serialassist::scanPorts()
{
    // 清空当前列表
    ui->cmbPortName->clear();

    // 获取可用串口列表
    QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();

    // 遍历并添加到下拉框
    foreach(const QSerialPortInfo &port, ports) {
        ui->cmbPortName->addItem(port.portName());
    }

    // 可选：如果没有找到串口
    if(ports.isEmpty()) {
        // ui->serialPortCoBox->addItem("No Ports Found");
        ui->cmbPortName->setDisabled(true);
        ui->btnOpenPort->setDisabled(true);
    } else {
        ui->cmbPortName->setEnabled(true);
        ui->btnOpenPort->setEnabled(true);
    }

}

void serialassist::setControlsEnabled(bool enabled)
{
    ui->cmbPortName->setEnabled(enabled);
    ui->cmbBaudRate->setEnabled(enabled);
    ui->cmbDataBits->setEnabled(enabled);
    ui->cmbParity->setEnabled(enabled);
    ui->cmbStopBits->setEnabled(enabled);
}

QSerialPort::StopBits serialassist::to_convert_stopbit(QString bit)
{
    if(bit == tr("1"))
        return QSerialPort::OneStop;
    else if (bit == tr("1.5"))
        return QSerialPort::OneAndHalfStop;
    else if (bit == tr("2"))
        return QSerialPort::TwoStop;
    return QSerialPort::OneStop;
}

QSerialPort::DataBits  serialassist::to_convert_databit(QString  bit)
{
    if(bit == tr("8"))
        return QSerialPort::Data8;
    if(bit == tr("7"))
        return QSerialPort::Data7;
    if(bit == tr("6"))
        return QSerialPort::Data6;
    if(bit == tr("5"))
        return QSerialPort::Data5;
    return QSerialPort::Data8;
}

QSerialPort::Parity  serialassist::to_convert_paritybit(QString  bit)
{
    if(bit == tr("None"))
        return QSerialPort::NoParity;
    if(bit == tr("Odd"))
        return QSerialPort::OddParity;
    if(bit == tr("Even"))
        return QSerialPort::EvenParity;
    if(bit == tr("Space"))
        return QSerialPort::SpaceParity;
    if(bit == tr("Mark"))
        return QSerialPort::MarkParity;
    return QSerialPort::NoParity;
}